﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Collections.Generic;

namespace CreatePerformanceCounters.Test
{
    [TestClass]
    public class PerformanceCounterControllerTest
    {
        private Mock<IPerformanceCounterRepository> _mock = null;

        [TestInitialize]
        public void Initialize()
        {
            MockInitialize();
        }

        private void MockInitialize()
        {
            _mock = new Mock<IPerformanceCounterRepository>();
        }

        [TestCleanup]
        public void Cleanup()
        {
            MockCleanup();
        }

        private void MockCleanup()
        {
            _mock = null;
        }

        #region Validate

        #region General Validations
        [TestMethod]
        public void ValidateValidString()
        {
            PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
            var counters = controller.Validate(TestHelper.ValidString);

            Assert.IsNotNull(counters);
            _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void ValidateEmptyString()
        {
            PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
            controller.Validate(string.Empty);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ValidateNullString()
        {
            PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
            controller.Validate(null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ValidateNotValidJsonString()
        {
            PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
            controller.Validate(TestHelper.NotValidString);
        }
        #endregion

        #region Validate Category
        [TestMethod]
        public void ValidateNullCategoryName()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Validate(TestHelper.NullCategoryName);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.NullCategoryName),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void ValidateEmptyCategoryName()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Validate(TestHelper.EmptyCategoryName);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.EmptyCategoryName),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void ValidateNullCategoryType()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Validate(TestHelper.NullCategoryType);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.NullCategoryType),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void ValidateWrongCategoryType()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Validate(TestHelper.WrongCategoryType);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.WrongCategoryType),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void ValidateNullCategoryWithZeroCounters1()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Validate(TestHelper.CategoryWithNoCounters1);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.CategoryWithNoCounters),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void ValidateNullCategoryWithZeroCounters2()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Validate(TestHelper.CategoryWithNoCounters2);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.CategoryWithNoCounters),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        #endregion

        #region Validate Performance Counter
        [TestMethod]
        public void ValidateNullPerformanceCounterName()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Validate(TestHelper.NullPerformanceCounterName);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.NullPerformanceCounterName), 
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void ValidateEmptyPerformanceCounterName()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Validate(TestHelper.EmptyPerformanceCounterName);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.EmptyPerformanceCounterName),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void ValidateNullPerformanceCounterType()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Validate(TestHelper.NullPerformanceCounterType);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.NullPerformanceCounterType),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void ValidateWrongPerformanceCounterType()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Validate(TestHelper.WrongPerformanceCounterType);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.WrongPerformanceCounterType),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        #endregion
        #endregion

        #region Create

        #region General Creations
        [TestMethod]
        public void CreateValidString()
        {
            PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
            controller.Create(TestHelper.ValidString);

            _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Once());
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void CreateEmptyString()
        {
            PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
            controller.Create(string.Empty);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateNullString()
        {
            PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
            controller.Create(null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void CreateNotValidJsonString()
        {
            PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
            controller.Create(TestHelper.NotValidString);
        }
        #endregion

        #region Category Issues
        [TestMethod]
        public void CreateNullCategoryName()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Create(TestHelper.NullCategoryName);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.NullCategoryName),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void CreateEmptyCategoryName()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Create(TestHelper.EmptyCategoryName);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.EmptyCategoryName),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void CreateNullCategoryType()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Create(TestHelper.NullCategoryType);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.NullCategoryType),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void CreateWrongCategoryType()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Create(TestHelper.WrongCategoryType);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.WrongCategoryType),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void CreateNullCategoryWithZeroCounters1()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Create(TestHelper.CategoryWithNoCounters1);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.CategoryWithNoCounters),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void CreateNullCategoryWithZeroCounters2()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Create(TestHelper.CategoryWithNoCounters2);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.CategoryWithNoCounters),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }
        #endregion

        #region Performance Counter Issues
        [TestMethod]
        public void CreateNullPerformanceCounterName()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Create(TestHelper.NullPerformanceCounterName);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.NullPerformanceCounterName),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void CreateEmptyPerformanceCounterName()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Create(TestHelper.EmptyPerformanceCounterName);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.EmptyPerformanceCounterName),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void CreateNullPerformanceCounterType()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Create(TestHelper.NullPerformanceCounterType);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.NullPerformanceCounterType),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }

        [TestMethod]
        public void CreateWrongPerformanceCounterType()
        {
            try
            {
                PerformanceCounterController controller = new PerformanceCounterController(_mock.Object);
                controller.Create(TestHelper.WrongPerformanceCounterType);
            }
            catch (ArgumentException ex)
            {
                Assert.IsTrue(ex.ToString().Contains(Messages.WrongPerformanceCounterType),
                    ex.ToString());

                _mock.Verify(m => m.Create(It.IsAny<List<PerformanceCounterCategory>>()), Times.Never());
            }
        }
        #endregion

        #endregion
    }
}